package cn.com.dhcc.turbo.dao.exch;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import cn.com.dhcc.app.core.CM;
import cn.com.dhcc.app.core.dao.AbstractCrudDao;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.FileSplitException;
import cn.com.dhcc.app.core.handler.filesplithandler.FileSplitService;
import cn.com.dhcc.app.core.handler.filesplithandler.FileSplitServiceFactory;
import cn.com.dhcc.app.core.handler.filesplithandler.FileSplitStatic.FILESPLIT_ALGORITHM;
import cn.com.dhcc.app.core.handler.filesplithandler.Packet;
import cn.com.dhcc.app.core.handler.modulehandler.WhereCondition;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.util.JsonUtil;
import cn.com.dhcc.app.pub.core.consts.AppConst;
import cn.com.dhcc.app.pub.core.util.ZipUtil;
import cn.com.dhcc.turbo.dao.registry.NodeInfoDao;
import cn.com.dhcc.turbo.entity.exch.CarvedDiscsData;
import cn.com.dhcc.turbo.entity.exch.CmData;
import cn.com.dhcc.turbo.entity.exch.CrossNetTmpCmData;
import cn.com.dhcc.turbo.entity.exch.CrossNetTmpFileData;
import cn.com.dhcc.turbo.entity.exch.FileData;
import cn.com.dhcc.turbo.entity.exch.SendCmData;
import cn.com.dhcc.turbo.entity.exch.SendFileData;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;

@Repository
public class CarvedDiscsDataDao extends AbstractCrudDao<CarvedDiscsData> {
	@SuppressWarnings("deprecation")
	private static Logger logger = Log.getExistLogger(LOGTYPE.SAI);
	
	@Autowired
	private SendFileDataDao sendFileDataDao;
	@Autowired
	private SendCmDataDao cmDataDao;
	
	@Autowired
	private CrossNetTmpFileDataDao crossNetTmpFileDataDao;
	@Autowired
	private CrossNetTmpCmDataDao crossNetTmpCmDataDao;
	@Autowired
	private NodeInfoDao nodeInfoDao;
	private static FileSplitService fileSplit = FileSplitServiceFactory.createFileSplitService(FILESPLIT_ALGORITHM.SIMPLE);
	public long sumFileSize(WhereCondition condtion) throws DaoException{
		List<String> list=CM.getDao().listSignleStringColumn("计算待刻盘总大小", "select to_char(sum(filesize)) from "+SI_TABLE("TURBO_CARVED_DISCS_DATA"), condtion, new Object[]{});
		if (list!=null && list.size()>=0) {
			if (list.get(0)!=null) {
				return Long.parseLong(list.get(0).toString());
			}
		}
		return 0;
	}
	
	/**
	 * 将每次请求打成zip包
	 * @param data
	 * @throws DaoException 
	 * @throws IOException 
	 * @throws FileNotFoundException 
	 * @throws FileSplitException 
	 */
	private void generateZip(CarvedDiscsData data) throws DaoException, FileNotFoundException, IOException, FileSplitException{
		NodeInfo localNode=nodeInfoDao.getLocalNode();
		String dataString=new SimpleDateFormat("yyyyMMDDHHmmss").format(new Date());
		File baseFile=new File( AppConst.APP_CD_TEMP,"sl_exch_"+localNode.getNodeCode()+"_"+dataString);//基本目录
		if (!baseFile.exists()) {
			baseFile.mkdirs();
		}
		//首先处理数据文件
		String[] strorepaths= data.getStorepaths().split(",");
		for (String strorepath : strorepaths) {
			String path = data.getFilehome() + File.separator + strorepath;
			File file = new File(path);
			if (file.exists()) {
					FileUtils.copyFile(file, new File(baseFile,data.getId()+File.separator+file.getName()));
			}else {
				baseFile=null;
				break;
			}
		}
		
		//处理记录文件
		Map<String,Object> map=new HashMap<String, Object>();
		map.put("carvedDiscsData", data);//刻盘的数据,格式为{"carvedDiscsData":{},"data":[{},{}]}
		WhereCondition parameter = new WhereCondition();
		if (data.getFromTable().equals(AppConst.FromTable.SEND_TABLE.value())) {//刻盘数据从send表中来
			if (data.getDataType().equals(AppConst.ExchDataType.FILE_DATA.value())) {//非结构化数据
				parameter.where().eq("group_id", data.getBatchId()).and().eq("cross_net", AppConst.CrossNetType.INNER_OUT_NETWORK.value());//查找到从内外到外网，group_id等于data的batchid
    			List<SendFileData> list=sendFileDataDao.list(parameter);
    			map.put("data", list);
			}else{//结构化数据
				parameter.where().eq("pid", data.getBatchId()).and().eq("cross_net", AppConst.CrossNetType.INNER_OUT_NETWORK.value());//查找到从内外到外网，pid等于data的batchid
    			List<SendCmData> list=cmDataDao.list(parameter);
    			map.put("data", list);
			}
		}else if(data.getFromTable().equals(AppConst.FromTable.TMP_TABLE.value())){//刻盘数据从tmp表中来
			if (data.getDataType().equals(AppConst.ExchDataType.FILE_DATA.value())) {
				parameter.where().eq("group_id", data.getBatchId()).and().eq("cross_net", AppConst.CrossNetType.OUT_INNER_NETWORK.value())
				.and().eq("THROUGH_GAP", "2");//从外网到内网，需要刻盘的非结构化数据
    			List<CrossNetTmpFileData> list=crossNetTmpFileDataDao.list(parameter);
    			map.put("data", list);
			}else{
				parameter.where().eq("pid", data.getBatchId()).and().eq("cross_net", AppConst.CrossNetType.OUT_INNER_NETWORK.value())
				.and().eq("THROUGH_GAP", "2");//从外网到内网，需要刻盘的结构化数据
    			List<CrossNetTmpCmData> list=crossNetTmpCmDataDao.list(parameter);
    			map.put("data", list);
			}
		}else{
			//
		}
		JsonUtil.toJsonFile(new File(baseFile,data.getId()+File.separator+data.getId()+".json"), map);
		
		//打成zip包，
		File zipDir=new File(AppConst.APP_CD_ZIP);
		if (!zipDir.exists()) {
			zipDir.mkdirs();
		}
		File zipFile= new File(zipDir.getAbsolutePath()+File.separator+baseFile.getName()+".zip");
		ZipUtil.compress(baseFile.getAbsolutePath(),zipFile.getAbsolutePath(), "gbk", "结构化数据压缩文件");
	
		data.setZipName(zipFile.getName());
		data.setZipSize(zipFile.length());
		
		//对zipfile进行拆包处理
		Packet packet=fileSplit.splitFile(zipFile, zipDir.getAbsolutePath(), AppConst.CD_FILESIZE, false);
		if (packet!=null && packet.getPacketfile().size()>1) {
			List<String> listFile=packet.getPacketfile();
			StringBuffer packets=new StringBuffer();//拆包后的每一个文件的路径
			StringBuffer packetsSize=new StringBuffer();//拆包后的每一个包的大小
			StringBuffer status=new StringBuffer();//刻盘状态
			for (String string : listFile) {
				packets.append(new File(string).getName()+",");
				packetsSize.append(new File(string).length()+",");
				status.append("0,");
			}
			packets.deleteCharAt(packets.length()-1);
			packetsSize.deleteCharAt(packetsSize.length()-1);
			status.deleteCharAt(status.length()-1);
			data.setPackets(packets.toString());
			data.setPacketsSize(packetsSize.toString());
			data.setStatus(status.toString());
		}else{
			data.setStatus("0");
		}
		
	}
	
	
	
	/**
	 * 根据cmData对象生成对应的CarvedDiscsData对象并且保存起来
	 * @param cmData
	 * @throws DaoException 
	 */
	public  void generateCarvedDiscsData(CmData cmData) throws DaoException{
		String msg=null;
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMDDHHmmss");
		try {
			CarvedDiscsData carvedDiscsData=this.getByBatchId(cmData.getPid());;
			if (carvedDiscsData!=null) {
				return;
			}
			carvedDiscsData=new CarvedDiscsData();
			
			//根据批次id查询有没有该记录
			//如果数据类型是SQL_DATA或者CM_DATA
			carvedDiscsData.setId("ORDER_"+sdf.format(cmData.getCreated())+"_"+cmData.getPid()+"_1_1");
			carvedDiscsData.setBatchId(cmData.getPid());
		
			carvedDiscsData.setSendNodecode(cmData.getSendNodecode());
			carvedDiscsData.setSendAdaptorcode(cmData.getSendAdaptorcode());
			StringBuffer recvNodecodes=new StringBuffer();
			StringBuffer recvAdaptorCodes=new StringBuffer();
			
			if(cmData instanceof SendCmData){
				List<SendCmData> sendCmDatas=null;
				if (cmData.getCrossNet().equals(AppConst.CrossNetType.INNER_OUT_NETWORK.value())) {
					sendCmDatas=CM.getDao().listModule("根据pid查询", "select * from "+SI_TABLE("turbo_send_cm_data")+" where pId=? and cross_net=?", SendCmData.class, new Object[]{cmData.getPid(),AppConst.CrossNetType.INNER_OUT_NETWORK.value()});
				}else if(cmData.getCrossNet().equals(AppConst.CrossNetType.OUT_INNER_NETWORK.value())){
					sendCmDatas=CM.getDao().listModule("根据pid查询", "select * from "+SI_TABLE("turbo_send_cm_data")+" where pId=? and cross_net=? and THROUGH_GAP='2'", SendCmData.class, new Object[]{cmData.getPid(),AppConst.CrossNetType.OUT_INNER_NETWORK.value()});
				}
				for (int i=0;i<sendCmDatas.size();i++) {
					SendCmData sendCmData=sendCmDatas.get(i);
					if(i==sendCmDatas.size()-1){
						recvNodecodes.append((sendCmData.getRecvNodecode()==null?"":sendCmData.getRecvNodecode()));
						recvAdaptorCodes.append(sendCmData.getRecvAdaptorcode());
					}else{
						recvNodecodes.append((sendCmData.getRecvNodecode()==null?"":sendCmData.getRecvNodecode())+",");
						recvAdaptorCodes.append(sendCmData.getRecvAdaptorcode()+",");
					}
				}
				carvedDiscsData.setFromTable(AppConst.FromTable.SEND_TABLE.value());
			}else if (cmData instanceof CrossNetTmpCmData) {
				List<CrossNetTmpCmData> crossNetTmpCmDatas=CM.getDao().listModule("根据pid查询", "select * from "+SI_TABLE("turbo_cross_net_tmp_file_data")+" where group_id=? and cross_net=? and THROUGH_GAP='2'", CrossNetTmpCmData.class, new Object[]{cmData.getPid(),AppConst.CrossNetType.OUT_INNER_NETWORK.value()});
				for (int i=0;i<crossNetTmpCmDatas.size();i++) {
					CrossNetTmpCmData crossNetTmpCmData=crossNetTmpCmDatas.get(i);
					if(i==crossNetTmpCmDatas.size()-1){
						recvNodecodes.append((crossNetTmpCmData.getRecvNodecode()==null?"":crossNetTmpCmData.getRecvNodecode()));
						recvAdaptorCodes.append(crossNetTmpCmData.getRecvAdaptorcode());
					}else{
						recvNodecodes.append((crossNetTmpCmData.getRecvNodecode()==null?"":crossNetTmpCmData.getRecvNodecode())+",");
						recvAdaptorCodes.append(crossNetTmpCmData.getRecvAdaptorcode()+",");
					}
				}
				carvedDiscsData.setFromTable(AppConst.FromTable.TMP_TABLE.value());
			}
			
			
			
			carvedDiscsData.setRecvNodecode(recvNodecodes.toString());
			carvedDiscsData.setRecvAdaptorcode(recvAdaptorCodes.toString());
			carvedDiscsData.setSendBusicode(cmData.getSendBusicode());
			carvedDiscsData.setPosthead(cmData.getPosthead());
			carvedDiscsData.setDataType(cmData.getDataType());
			carvedDiscsData.setAuditPerson(cmData.getAuditPerson());
			carvedDiscsData.setRequestDate(cmData.getCreated());
			carvedDiscsData.setFilehome(AppConst.CMDATA_STORED_DIR);
			carvedDiscsData.setFilepaths(cmData.getPayload());
			carvedDiscsData.setStorepaths(cmData.getPayload());
			File file=new File(AppConst.CMDATA_STORED_DIR + File.separator + cmData.getPayload());
			if (file.exists()) {
				carvedDiscsData.setFilesize(file.length());
			}else{
				msg = "生成对应的CarvedDiscsData对象失败";
				FileNotFoundException e=new FileNotFoundException("落地文件丢失");
				logger.error(msg, e);
				throw new DaoException(msg, e);
			}
			this.generateZip(carvedDiscsData);//进行打包拆包
			
			this.insertOrUpdate(carvedDiscsData);
		} catch (Exception e) {
			msg = "生成对应的CarvedDiscsData对象失败";
			logger.error(msg, e);
			throw new DaoException(msg, e);
		}
		
	}
	
	public CarvedDiscsData getByBatchId(String batchId) throws DaoException{
		String sql="select * from "+SI_TABLE("TURBO_CARVED_DISCS_DATA")+" where batch_id=?";
		
		return  CM.getDao().getModule("", sql, CarvedDiscsData.class, new Object[]{batchId});
	}
	
	/**
	 * 根据cmData对象生成对应的CarvedDiscsData对象并且保存起来
	 * @param cmData
	 * @throws DaoException 
	 */
	public  void generateCarvedDiscsData(FileData fileData) throws DaoException{
		String msg=null;
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMDDHHmmss");
		try {
			CarvedDiscsData carvedDiscsData=this.getByBatchId(fileData.getGroupId());
			if (carvedDiscsData!=null) {
				return;
			}
			carvedDiscsData=new CarvedDiscsData();
			
			//根据批次id查询有没有该记录
			//如果数据类型是SQL_DATA或者CM_DATA
			carvedDiscsData.setId("ORDER_"+sdf.format(fileData.getCreated())+"_"+fileData.getGroupId()+"_1_1");
			carvedDiscsData.setBatchId(fileData.getGroupId());
			
			carvedDiscsData.setSendNodecode(fileData.getSendNodecode());
			carvedDiscsData.setSendAdaptorcode(fileData.getSendAdaptorcode());
			
			StringBuffer recvNodecodes=new StringBuffer();
			StringBuffer recvAdaptorCodes=new StringBuffer();
			if(fileData instanceof SendFileData){
				List<SendFileData> sendFileDatas=null;
				if (fileData.getCrossNet().equals(AppConst.CrossNetType.INNER_OUT_NETWORK.value())) {
					sendFileDatas=CM.getDao().listModule("根据pid查询", "select * from "+SI_TABLE("turbo_send_file_data")+" where group_id=? and cross_net=?", SendFileData.class, new Object[]{fileData.getGroupId(),AppConst.CrossNetType.INNER_OUT_NETWORK.value()});
				}else if(fileData.getCrossNet().equals(AppConst.CrossNetType.OUT_INNER_NETWORK.value())){
					sendFileDatas=CM.getDao().listModule("根据pid查询", "select * from "+SI_TABLE("turbo_send_file_data")+" where group_id=? and cross_net=? and THROUGH_GAP='2'", SendFileData.class, new Object[]{fileData.getGroupId(),AppConst.CrossNetType.OUT_INNER_NETWORK.value()});
				}
				for (int i=0;i<sendFileDatas.size();i++) {
					SendFileData sendFileData=sendFileDatas.get(i);
					if(i==sendFileDatas.size()-1){
						recvNodecodes.append((sendFileData.getRecvNodecode()==null?"":sendFileData.getRecvNodecode()));
						recvAdaptorCodes.append(sendFileData.getRecvAdaptorcode());
					}else{
						recvNodecodes.append((sendFileData.getRecvNodecode()==null?"":sendFileData.getRecvNodecode())+",");
						recvAdaptorCodes.append(sendFileData.getRecvAdaptorcode()+",");
					}
				}
				carvedDiscsData.setFromTable(AppConst.FromTable.SEND_TABLE.value());
			}else if (fileData instanceof CrossNetTmpFileData) {
				List<CrossNetTmpFileData> crossNetTmpFileDatas=CM.getDao().listModule("根据pid查询", "select * from "+SI_TABLE("turbo_cross_net_tmp_file_data")+" where group_id=? and cross_net=? and THROUGH_GAP='2'", CrossNetTmpFileData.class, new Object[]{fileData.getGroupId(),AppConst.CrossNetType.OUT_INNER_NETWORK.value()});
				for (int i=0;i<crossNetTmpFileDatas.size();i++) {
					CrossNetTmpFileData crossNetTmpFileData=crossNetTmpFileDatas.get(i);
					if(i==crossNetTmpFileDatas.size()-1){
						recvNodecodes.append((crossNetTmpFileData.getRecvNodecode()==null?"":crossNetTmpFileData.getRecvNodecode()));
						recvAdaptorCodes.append(crossNetTmpFileData.getRecvAdaptorcode());
					}else{
						recvNodecodes.append((crossNetTmpFileData.getRecvNodecode()==null?"":crossNetTmpFileData.getRecvNodecode())+",");
						recvAdaptorCodes.append(crossNetTmpFileData.getRecvAdaptorcode()+",");
					}
				}
				carvedDiscsData.setFromTable(AppConst.FromTable.TMP_TABLE.value());
			}
			
			carvedDiscsData.setRecvNodecode(recvNodecodes.toString());
			carvedDiscsData.setRecvAdaptorcode(recvAdaptorCodes.toString());
			
			carvedDiscsData.setSendBusicode(fileData.getSendBusicode());
			carvedDiscsData.setPosthead(fileData.getPosthead());
			carvedDiscsData.setDataType(AppConst.ExchDataType.FILE_DATA.value());
			carvedDiscsData.setAuditPerson(fileData.getAuditPerson());
			carvedDiscsData.setRequestDate(fileData.getCreated());
			carvedDiscsData.setFilehome(fileData.getFilehome());
			carvedDiscsData.setFilepaths(fileData.getFilepaths());
			carvedDiscsData.setStorepaths(fileData.getStorepaths());
			carvedDiscsData.setFilesize(fileData.getFilesize());
			this.generateZip(carvedDiscsData);//进行打包拆包
			this.insert(carvedDiscsData);
		} catch (Exception e) {
			msg = "生成对应的CarvedDiscsData对象失败";
			logger.error(msg, e);
			throw new DaoException(msg, e);
		}
		
	}
	
	/** 
	 * @Description:把list转换为一个用逗号分隔的字符串 
	 */  
	@SuppressWarnings({ "unused", "rawtypes" })
	private  String listToString(List list) {  
	    StringBuilder sb = new StringBuilder();  
	    if (list != null && list.size() > 0) {  
	        for (int i = 0; i < list.size(); i++) {  
	            if (i < list.size() - 1) {  
	                sb.append(list.get(i) + ",");  
	            } else {  
	                sb.append(list.get(i));  
	            }  
	        }  
	    }  
	    return sb.toString();  
	}  
//	public static void main(String[] args) {
//		String[] sd=new String[]{"0","1","0"};
//		System.out.println(ArrayUtils.indexOf(sd, "33"));//
//		System.out.println("00".split(";").length);//
//		Object obj="123";
//		System.out.println(obj.toString());
//	}
	
}
